//主要功能是将接收到的信息进行格式化
#ifndef FORMATTER_HPP
#define FORMATTER_HPP
#include "logMessage.hpp"
#include <vector>
#include <sstream>
namespace blog
{
    class formatItem
    {
    public:
        using ptr = std::shared_ptr<formatItem>;
        //virtual ~formatItem();
        virtual void format(std::ostream &os,const logMessage& message)=0;
    };
    class msgFormatItem:public formatItem
    {
    public:
        msgFormatItem(const std::string&str=""){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<message._payload;
        }
    };
    class levelFormatItem:public formatItem
    {
    public:
        levelFormatItem(const std::string&str=""){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<logLevel::toString(message._level);
        }  
    };
    class nameFormatItem:public formatItem
    {
    public:
        nameFormatItem(const std::string&str=""){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<message._loggerName;
        }
    };
    class threadFormatItem:public formatItem
    {
    public:
        threadFormatItem(const std::string&str=""){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<message._pid;
        }
    };
    //这个后面可以回顾看看
    class timeFormatItem:public formatItem
    {
    private:
        std::string _format;
    public:
        timeFormatItem(const std::string& format="%H:%M:%S"):_format(format){}
        void format(std::ostream&os,const logMessage&message)override
        {
            time_t t=message._time;
            struct tm lt;
            localtime_r(&t,&lt);
            char tmp[128];
            strftime(tmp,127,_format.c_str(),&lt);
            os<<tmp;
        }
    };
    class cLineFormatItem:public formatItem
    {
    public:
        cLineFormatItem(const std::string&str=""){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<message._line;
        }
    };
    class cFileFormatItem:public formatItem
    {
    public:
        cFileFormatItem(const std::string&str=""){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<message._fileName;
        }
    };
    class nLineFormatItem:public formatItem
    {
    public:
        nLineFormatItem(const std::string&str=""){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<"\n";
        }
    };
    class tabFormatItem:public formatItem
    {
    public:
        tabFormatItem(const std::string&str=""){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<"\t";
        }
    };
    class otherFormatItem:public formatItem
    {
    private:
        std::string _str;
    public:
        otherFormatItem(const  std::string& str=""):_str(str){}
        void format(std::ostream&os,const logMessage&message)override
        {
            os<<_str;
        }
    };
    /*
    %d ⽇期
    %T 缩进
    %t 线程id
    %p ⽇志级别
    %c ⽇志器名称
    %f ⽂件名
    %l ⾏号
    %m ⽇志消息
    %n 换⾏
    */
    class formatter
    {
    public:
        using ptr =std::shared_ptr<formatter>;
        formatter(std::string pattern="[%d{%H:%M:%S}][%p][%c][t][%f:%l]%T%m%n"):_pattern(pattern)
        {
            prasePattern();
        }
        std::string format(const blog::logMessage& msg)
        {
            std::stringstream ss;
            for(auto&it:_item)
            {
                it->format(ss,msg);
            }
            return ss.str();
        }
        std::ostream& format(std::ostream&os,const blog::logMessage& msg)
        {
            for(auto&it:_item)
            {
                it->format(os,msg);
            }
            return os;
        }
    private:
        void prasePattern()
        {
            std::string val,key;
            std::vector<std::pair<std::string,std::string>> container;
            int pos=0;
            while(pos<_pattern.size())
            {
                //adad[%d{%H:%M:%S}][%p][%c][%t][%f:%l]%T%n
                //不是格式化字符
                while(_pattern[pos]!='%')
                {
                    if(pos<_pattern.size())
                    {
                    val.push_back(_pattern[pos++]);
                    }
                    else break;
                }
                container.push_back(std::make_pair("",val));
                val.clear();
                //遇到了格式化字符
                //if(pos>_pattern.size()) return;
                if(_pattern[pos]=='%')
                {
                    if(pos+1<_pattern.size()&&_pattern[pos+1]=='%')//处理转义字符
                        {val.push_back(_pattern[pos]); pos+=2;continue;}
                    //正常的格式化字符
                    key.push_back(_pattern[++pos]);pos++;
                }
                //遇到了格式化中的子格式化
                if(_pattern[pos]=='{')
                {
                    pos++;
                    while(pos<_pattern.size()&&_pattern[pos]!='}')
                    {
                        val.push_back(_pattern[pos++]);
                    }
                    if(pos>=_pattern.size())
                    {
                        std::cerr<<"{}不匹配"<<std::endl;
                        exit(1);
                    }
                    ++pos;//跳过}
                }
                container.push_back(std::make_pair(key,val));
                key.clear();
                val.clear();
            }
            //pattern解析完毕,开始装填item;
            for(auto&x:container)
            {
                _item.push_back(createItem(x.first,x.second));
            }
        }
      
        formatItem::ptr createItem(std::string key,std::string val)
        /*
        %d ⽇期
        %T 缩进
        %t 线程id
        %p ⽇志级别
        %c ⽇志器名称
        %f ⽂件名
        %l ⾏号
        %m ⽇志消息
        %n 换⾏
        */
        {
            if(key=="d")
            {
            if(val.empty()) return std::make_shared<timeFormatItem>();
            return std::make_shared<timeFormatItem>(val);
            }
            if(key=="t")    return std::make_shared<threadFormatItem>(val);
            if(key=="p")    return std::make_shared<levelFormatItem>(val);
            if(key=="c")    return std::make_shared<nameFormatItem>(val);
            if(key=="f")    return std::make_shared<cFileFormatItem>(val);
            if(key=="l")    return std::make_shared<cLineFormatItem>(val);
            if(key=="m")    return std::make_shared<msgFormatItem>(val);
            if(key=="n")    return std::make_shared<nLineFormatItem>(val);
            if(key=="T")    return std::make_shared<tabFormatItem>(val);
            return std::make_shared<otherFormatItem>(val);

        }
        std::string _pattern;
        std::vector<formatItem::ptr>  _item;
    };
}

#endif